package cn.melonlib.cores.jpa.comp;

import cn.melonlib.cores.commons.model.entity.IEntity;
import cn.melonlib.cores.jpa.model.bean.PersistenceResult;
import org.intellij.lang.annotations.Language;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.metamodel.EntityType;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
 * 持久化接口
 */
public interface Dao {

    /**
     * 是否完成初始化
     * @return
     */
    boolean isInit();

    <ENTITY extends IEntity<? extends Serializable>> ENTITY lock(ENTITY entity) throws Exception;

    /**
     * 查询，通过传入不同的查询语句获取数据
     * @param query 查询语句
     * @param <DATA> 获取查询结果
     * @return
     */
    <DATA,QUERY extends CharSequence> PersistenceResult<DATA> search(QUERY query);

    /**
     * 自定义查询
     * @param worker 执行查询回调
     * @param <DATA> 返回类型
     * @return 返回查询结果
     */
    <DATA> PersistenceResult<DATA> query(Function<EntityManager,DATA> worker);



    /**
     * 获取单个实体对象
     * @param template 数据模板
     * @param id 主键值
     * @param <DATA> 数据
     * @param <PK> 主键
     * @return 对象
     */
    <DATA,PK extends Serializable> DATA getEntity(Class<DATA> template,PK id);

    /**
     * 保存一个对象，如果有主键值则修改，否则新增
     * @param entity 保存对象
     * @param <ENTITY> 对象类型
     * @return 返回保存并绑定的对象(包含主键值)
     */
    <ENTITY extends IEntity> PersistenceResult<ENTITY> save(ENTITY entity);

    /**
     * 删除一个对象
     * @param entity 需要删除对象
     * @param <ENTITY> 对象类型
     * @return 删除的个数
     */
    <ENTITY extends IEntity> PersistenceResult<Integer> remove(ENTITY entity);

    /**
     * 通过主键值来删除一个对象
     * @param entityClass
     * @param id
     * @return
     */
    PersistenceResult<Integer> removeById(Class<? extends IEntity> entityClass, Serializable id);

    /**
     * 删除多个对象
     * @param entities
     * @return
     */
    PersistenceResult<Integer> removeMulti(List<? extends IEntity> entities);

    /**
     * 通过主键值删除多个对象
     * @param target
     * @param ids 主键值，逗号分割
     * @return
     */
    PersistenceResult<Integer> removeMultiByKeys(String target, String ids);

    /**
     * 通过主键值删除多个对象
     * @param target
     * @param ids
     * @return
     */
    PersistenceResult<Integer> removeMultiByKeys(String target, List<? extends Serializable> ids);

    /**
     * 通过主键值删除多个对象
     * @param target
     * @param ids
     * @return
     */
    PersistenceResult<Integer> removeMultiByKeys(Class target, List<? extends Serializable> ids);

    /**
     * 自定义更新
     * @param worker 更新代码
     * @return 返回影响数据行
     */
    PersistenceResult<Integer> update(Function<EntityManager,Integer> worker);
    /**
     * 更新缓存内容
     * @return
     */
    Dao flush();

    /**
     * 手动打开一个连接，一般不必使用
     * @return
     */
    Dao open();

    /**
     * 手动关闭一个连接，一般不必使用
     * @return
     */
    Dao close();

    /**
     * 手动提交一个事务，一般不必使用
     * @return
     */
    Dao commit();

    /**
     * 手动回滚事务，一般不必使用
     * @return
     */
    Dao rollback();

    /**
     * 获取一个被注册的实体描述对象
     * @param name 实体模板名称
     * @return 描述实体的对象
     */
    EntityType getType(String name);

    /**
     * 获取一个被注册实体的模板类型
     * @param name 实体模板类型的名称
     * @return 模板类型对象
     */
    Class getTypeClass(String name);

    /**
     * 获取所有的被注册的实体对象模板
     * @return
     */
    Map<String,EntityType> getAllTypes();

    /**
     * 执行一个更新语句
     * @param ql 语句
     * @param params 需要传入的参数
     * @return 返回操作影响的行数
     */
    int updateQl(@Language("HQL") String ql, List<? extends Serializable> params);

//    int copy(Class<? extends IEntity<? extends Serializable>> source, Class<? extends IEntity<? extends Serializable>> target, Set<String> fields);

    /**
     * 查询并转换数据到对象
     * @param query 需要转换的查询
     * @param voClass 需要转换的模板
     * @param <VO> 定义转换模板类型
     * @return 转换后的数据
     */
    <VO>List<VO> queryToVo(Query query, Class<VO> voClass) ;


}
